﻿using Lib.Data.Entitys;
using Lib.Data.Enumeration;
using System.Collections;
using System.Data;
using System.Data.Common;
using System.Diagnostics;
using System.Text;

namespace Lib.Data;

public static partial class DBCommon {

    #region "ExecuteNonQuery"

    /// <summary>
    /// 执行（新增、删除、更新）SQL语句或存储过程, 并返回受影响的行数
    /// </summary>
    public static int ExecuteNonQuery(this DataBase db, string SQL, IList<DbParameter> cmdParams = null, CommandType cmdType = CommandType.Text, ConnectionStatus ConnectionStatus = ConnectionStatus.None) {
        var CMD = db.Index > -1 ? db.CMD : db.Provider.CreateCommand();
        if (db.Index == -1) {
            CMD.Connection = db.Conn;
        }
        CMD.CommandType = cmdType;
        CMD.CommandText = SQL;
        DBCommon.AddParameter(db, CMD, cmdParams);
        if (ConnectionStatus == ConnectionStatus.None) {
            ConnectionStatus = db.ConnectionStatus;
        }
        int i = 0;
        string Message = null;
        var Timer = Stopwatch.StartNew();
        try {
            CMD.Resolve(db);
            if (db.Index == -1 && db.Conn.State == ConnectionState.Closed) {
                db.Conn.Open();
            }
            Timer.Restart();
            i = CMD.ExecuteNonQuery();
            Timer.Stop();
        } catch (Exception ex) {
            if (db.Index > -1) {
                db.Index++;
            }
            Message = ex.Message;
            if (db.IsDevelopment) {
                throw;
            }
        } finally {
            //
            DBCommon.ProcessReturnValue(CMD, cmdParams);
            //
            if (db.Index == -1 && ConnectionStatus == ConnectionStatus.CloseOnExit) {
                db.Conn.Close();
            }
            if (db.LogEnable) {
                WriteLog(db, CMD, Timer, "ExecuteNonQuery", Message);
            }
            if (db.Index == -1) {
                CMD.Dispose();
            } else {
                CMD.Parameters.Clear();
            }
        }
        return i;
    }
    /// <summary>
    /// 执行（新增、删除、更新）SQL语句或存储过程, 并返回受影响的行数
    /// </summary>
    public static async Task<int> ExecuteNonQueryAsync(this DataBase db, string SQL, IList<DbParameter> cmdParams = null, CommandType cmdType = CommandType.Text, ConnectionStatus ConnectionStatus = ConnectionStatus.None) {
        var CMD = db.Index > -1 ? db.CMD : db.Provider.CreateCommand();
        if (db.Index == -1) {
            CMD.Connection = db.Conn;
        }
        CMD.CommandType = cmdType;
        CMD.CommandText = SQL;
        DBCommon.AddParameter(db, CMD, cmdParams);
        int i = 0;
        string Message = null;
        var Timer = Stopwatch.StartNew();
        try {
            CMD.Resolve(db);
            if (db.Index == -1 && db.Conn.State == ConnectionState.Closed) {
                await db.Conn.OpenAsync();
            }
            Timer.Restart();
            i = await CMD.ExecuteNonQueryAsync();
            Timer.Stop();
        } catch (Exception ex) {
            if (db.Index > -1) {
                db.Index++;
            }
            Message = ex.Message;
            if (db.IsDevelopment) {
                throw;
            }
        } finally {
            //
            DBCommon.ProcessReturnValue(CMD, cmdParams);
            //
            if (db.Index == -1 && ConnectionStatus == ConnectionStatus.CloseOnExit) {
                await db.Conn.CloseAsync();
            }
            if (db.LogEnable) {
                WriteLog(db, CMD, Timer, "ExecuteNonQuery", Message);
            }
            if (db.Index == -1) {
                CMD.Dispose();
            } else {
                CMD.Parameters.Clear();
            }
        }
        return i;
    }

    #endregion

    #region "ExecuteScalar"

    /// <summary>
    /// 执行查询SQL语句或存储过程并返回第一个返回的结果集中第一行的第一列, 若没有结果, 将返回 NULL
    /// </summary>
    public static T ExecuteScalar<T>(this DataBase db, string SQL, IList<DbParameter> cmdParams = null, CommandType cmdType = CommandType.Text, ConnectionStatus ConnectionStatus = ConnectionStatus.None) {
        var CMD = db.Index > -1 ? db.CMD : db.Provider.CreateCommand();
        if (db.Index == -1) {
            CMD.Connection = db.Conn;
        }
        CMD.CommandType = cmdType;
        CMD.CommandText = SQL;
        DBCommon.AddParameter(db, CMD, cmdParams);
        T Result = default;
        string Message = null;
        var Timer = Stopwatch.StartNew();
        try {
            CMD.Resolve(db);
            if (db.Index == -1 && db.Conn.State == ConnectionState.Closed) {
                db.Conn.Open();
            }
            Timer.Restart();
            Result = CMD.ExecuteScalar().ChanageType<T>();
            Timer.Stop();
        } catch (Exception ex) {
            if (db.Index > -1) {
                db.Index++;
            }
            Message = ex.Message;
            if (db.IsDevelopment) {
                throw;
            }
        } finally {
            //
            DBCommon.ProcessReturnValue(CMD, cmdParams);
            //
            if (db.Index == -1 && ConnectionStatus == ConnectionStatus.CloseOnExit) {
                db.Conn.Close();
            }
            if (db.LogEnable) {
                WriteLog(db, CMD, Timer, "ExecuteScalar", Message);
            }
            if (db.Index == -1) {
                CMD.Dispose();
            } else {
                CMD.Parameters.Clear();
            }
        }
        return Result;
    }
    /// <summary>
    /// 执行查询SQL语句或存储过程并返回第一个返回的结果集中第一行的第一列, 若没有结果, 将返回 NULL
    /// </summary>
    public static async Task<T> ExecuteScalarAsync<T>(this DataBase db, string SQL, IList<DbParameter> cmdParams = null, CommandType cmdType = CommandType.Text, ConnectionStatus ConnectionStatus = ConnectionStatus.None) {
        var CMD = db.Index > -1 ? db.CMD : db.Provider.CreateCommand();
        if (db.Index == -1) {
            CMD.Connection = db.Conn;
        }
        CMD.CommandType = cmdType;
        CMD.CommandText = SQL;
        DBCommon.AddParameter(db, CMD, cmdParams);
        T Result = default;
        string Message = null;
        var Timer = Stopwatch.StartNew();
        try {
            CMD.Resolve(db);
            if (db.Index == -1 && db.Conn.State == ConnectionState.Closed) {
                await db.Conn.OpenAsync();
            }
            Timer.Restart();
            var _Result = await CMD.ExecuteScalarAsync();
            Result = _Result.ChanageType<T>();
            Timer.Stop();
        } catch (Exception ex) {
            if (db.Index > -1) {
                db.Index++;
            }
            Message = ex.Message;
            if (db.IsDevelopment) {
                throw;
            }
        } finally {
            //
            DBCommon.ProcessReturnValue(CMD, cmdParams);
            //
            if (db.Index == -1 && ConnectionStatus == ConnectionStatus.CloseOnExit) {
                await db.Conn.CloseAsync();
            }
            if (db.LogEnable) {
                WriteLog(db, CMD, Timer, "ExecuteScalar", Message);
            }
            if (db.Index == -1) {
                CMD.Dispose();
            } else {
                CMD.Parameters.Clear();
            }
        }
        return Result;
    }

    #endregion

    #region "ExecuteReader"

    /// <summary>
    /// 执行“查询SQL语句”或“存储过程”<para />
    /// 使用方法：<para />
    /// using(var Reader = db.ExecuteReader(...)){ while (Reader.Read()) { ... } }<para />
    /// </summary>
    public static DataReader ExecuteReader(this DataBase db, string SQL, IList<DbParameter> cmdParams = null, CommandType cmdType = CommandType.Text, ConnectionStatus ConnectionStatus = ConnectionStatus.None) {
        var CMD = db.Index > -1 ? db.CMD : db.Provider.CreateCommand();
        if (db.Index == -1) {
            CMD.Connection = db.Conn;
        }
        CMD.CommandType = cmdType;
        CMD.CommandText = SQL;
        DBCommon.AddParameter(db, CMD, cmdParams);
        DataReader Reader = null;
        string Message = null;
        var Timer = Stopwatch.StartNew();
        try {
            CMD.Resolve(db);
            if (db.Index == -1 && db.Conn.State == ConnectionState.Closed) {
                db.Conn.Open();
            }
            Timer.Restart();
            if (ConnectionStatus == ConnectionStatus.CloseOnExit) {
                Reader = new DataReader(CMD.ExecuteReader(CommandBehavior.CloseConnection));
            } else {
                Reader = new DataReader(CMD.ExecuteReader());
            }
            Timer.Stop();
        } catch (Exception ex) {
            if (db.Index > -1) {
                db.Index++;
            }
            Message = ex.Message;
            if (db.IsDevelopment) {
                throw;
            }
        } finally {
            //
            DBCommon.ProcessReturnValue(CMD, cmdParams);
            //
            if (db.LogEnable) {
                WriteLog(db, CMD, Timer, "ExecuteReader", Message);
            }
            if (db.Index == -1) {
                CMD.Dispose();
            } else {
                CMD.Parameters.Clear();
            }
        }
        return Reader;
    }
    /// <summary>
    /// 执行“查询SQL语句”或“存储过程”<para />
    /// 使用方法：<para />
    /// using(var Reader = await db.ExecuteReaderAsync(...)){ while (Reader.Read()) { ... } }<para />
    /// </summary>
    public static async Task<DataReader> ExecuteReaderAsync(this DataBase db, string SQL, IList<DbParameter> cmdParams = null, CommandType cmdType = CommandType.Text, ConnectionStatus ConnectionStatus = ConnectionStatus.None) {
        var CMD = db.Index > -1 ? db.CMD : db.Provider.CreateCommand();
        if (db.Index == -1) {
            CMD.Connection = db.Conn;
        }
        CMD.CommandType = cmdType;
        CMD.CommandText = SQL;
        DBCommon.AddParameter(db, CMD, cmdParams);
        DataReader Reader = null;
        string Message = null;
        var Timer = Stopwatch.StartNew();
        try {
            CMD.Resolve(db);
            if (db.Index == -1 && db.Conn.State == ConnectionState.Closed) {
                await db.Conn.OpenAsync();
            }
            Timer.Restart();
            if (ConnectionStatus == ConnectionStatus.CloseOnExit) {
                Reader = new DataReader(await CMD.ExecuteReaderAsync(CommandBehavior.CloseConnection));
            } else {
                Reader = new DataReader(await CMD.ExecuteReaderAsync());
            }
            Timer.Stop();
        } catch (Exception ex) {
            if (db.Index > -1) {
                db.Index++;
            }
            Message = ex.Message;
            if (db.IsDevelopment) {
                throw;
            }
        } finally {
            //
            DBCommon.ProcessReturnValue(CMD, cmdParams);
            //
            if (db.LogEnable) {
                WriteLog(db, CMD, Timer, "ExecuteReader", Message);
            }
            if (db.Index == -1) {
                CMD.Dispose();
            } else {
                CMD.Parameters.Clear();
            }
        }
        return Reader;
    }

    #endregion

    #region "ExecuteDataSet"

    /// <summary>
    /// 执行“查询SQL语句”或“存储过程”
    /// </summary>
    public static DataSet ExecuteDataSet(this DataBase db, string SQL, IList<DbParameter> cmdParams = null, CommandType cmdType = CommandType.Text, ConnectionStatus ConnectionStatus = ConnectionStatus.None) {
        var CMD = db.Index > -1 ? db.CMD : db.Provider.CreateCommand();
        if (db.Index == -1) {
            CMD.Connection = db.Conn;
        }
        CMD.CommandType = cmdType;
        CMD.CommandText = SQL;
        DBCommon.AddParameter(db, CMD, cmdParams);
        var Adapter = db.Provider.CreateDataAdapter();
        Adapter.SelectCommand = CMD;
        var DS = new DataSet();
        string Message = null;
        var Timer = Stopwatch.StartNew();
        try {
            CMD.Resolve(db);
            if (db.Index == -1 && db.Conn.State == ConnectionState.Closed) {
                db.Conn.Open();
            }
            Timer.Restart();
            Adapter.Fill(DS);
            Timer.Stop();
        } catch (Exception ex) {
            if (db.Index > -1) {
                db.Index++;
            }
            DS = null;
            Message = ex.Message;
            if (db.IsDevelopment) {
                throw;
            }
        } finally {
            //
            DBCommon.ProcessReturnValue(CMD, cmdParams);
            //
            if (db.Index == -1 && ConnectionStatus == ConnectionStatus.CloseOnExit) {
                db.Conn.Close();
            }
            if (db.LogEnable) {
                WriteLog(db, CMD, Timer, "ExecuteDataSet", Message);
            }
            if (db.Index == -1) {
                CMD.Dispose();
            } else {
                CMD.Parameters.Clear();
            }
        }
        return DS;
    }
    /// <summary>
    /// 执行“查询SQL语句”或“存储过程”
    /// </summary>
    public static async Task<DataSet> ExecuteDataSetAsync(this DataBase db, string SQL, IList<DbParameter> cmdParams = null, CommandType cmdType = CommandType.Text, ConnectionStatus ConnectionStatus = ConnectionStatus.None) {
        var CMD = db.Index > -1 ? db.CMD : db.Provider.CreateCommand();
        if (db.Index == -1) {
            CMD.Connection = db.Conn;
        }
        CMD.CommandType = cmdType;
        CMD.CommandText = SQL;
        DBCommon.AddParameter(db, CMD, cmdParams);
        var Adapter = db.Provider.CreateDataAdapter();
        Adapter.SelectCommand = CMD;
        var DS = new DataSet();
        string Message = null;
        var Timer = Stopwatch.StartNew();
        try {
            CMD.Resolve(db);
            if (db.Index == -1 && db.Conn.State == ConnectionState.Closed) {
                await db.Conn.OpenAsync();
            }
            Timer.Restart();
            Adapter.Fill(DS);
            Timer.Stop();
        } catch (Exception ex) {
            if (db.Index > -1) {
                db.Index++;
            }
            DS = null;
            Message = ex.Message;
            if (db.IsDevelopment) {
                throw;
            }
        } finally {
            //
            DBCommon.ProcessReturnValue(CMD, cmdParams);
            //
            if (db.Index == -1 && ConnectionStatus == ConnectionStatus.CloseOnExit) {
                await db.Conn.CloseAsync();
            }
            if (db.LogEnable) {
                WriteLog(db, CMD, Timer, "ExecuteDataSet", Message);
            }
            if (db.Index == -1) {
                CMD.Dispose();
            } else {
                CMD.Parameters.Clear();
            }
        }
        return DS;
    }

    #endregion

    #region "ExecuteDataTable"

    /// <summary>
    /// 执行“查询SQL语句”或“存储过程”
    /// </summary>
    public static DataTable ExecuteDataTable(this DataBase db, string SQL, IList<DbParameter> cmdParams = null, CommandType cmdType = CommandType.Text, ConnectionStatus ConnectionStatus = ConnectionStatus.None) {
        DataTable dt = null;
        DataSet ds = db.ExecuteDataSet(SQL, cmdParams, cmdType, ConnectionStatus);
        if (ds != null && ds.Tables.Count > 0) {
            dt = ds.Tables[0];
        }
        return dt;
    }
    /// <summary>
    /// 执行“查询SQL语句”或“存储过程”
    /// </summary>
    public static async Task<DataTable> ExecuteDataTableAsync(this DataBase db, string SQL, IList<DbParameter> cmdParams = null, CommandType cmdType = CommandType.Text, ConnectionStatus ConnectionStatus = ConnectionStatus.None) {
        DataTable dt = null;
        DataSet ds = await db.ExecuteDataSetAsync(SQL, cmdParams,cmdType, ConnectionStatus);
        if (ds != null && ds.Tables.Count > 0) {
            dt = ds.Tables[0];
        }
        return dt;
    }

    #endregion

    #region "WriteLog、Parse、Resolve"

    /// <summary>
    /// 执行前处理
    /// </summary>
    internal static void Resolve(this DbCommand CMD, DataBase db) {
        if (db.dbType == dbType.Oracle) {
            CMD.GetType().GetProperty("BindByName").SetValue(CMD, true);
        }
    }

    /// <summary>
    /// 
    /// </summary>
    internal static void WriteLog(DataBase db, DbCommand CMD, Stopwatch Timer, string Handler, string Message) {
        //
        var IsException = !string.IsNullOrEmpty(Message);
        //
        var Key = $"{db.LogKey}{(string.IsNullOrEmpty(Message) ? null : ".Err")}";
        //
        if (db.RecordTime == 0 || !string.IsNullOrEmpty(Message) || (db.RecordTime > 0 && Timer.ElapsedMilliseconds > db.RecordTime)) {
            //
            var (SQL, cmdParms) = Parse(CMD);
            //
            // var sb = new StringBuilder();
            //
            // sb.Append($"执行时间：{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}<br/>");
            //
            // sb.Append($"执行方法：{Handler} {(IsException? "出错" : "")}<br/>");
            //
            // sb.Append($"命令类型：{(CMD.CommandType == CommandType.StoredProcedure ? "存储过程" : "SQL语句")}<br/>");            //
            //
            // sb.Append($"命令语句：{SQL}<br/>");
            //
            // sb.Append($"执行用时：{Timer.ElapsedMilliseconds} 毫秒<br/>"); 
            //
            // sb.Append($"{(CMD.Parameters.Count > 0 ? cmdParms : null)}");
            //
            // sb.Append($"{(IsException? $"异常信息：{Message}<br/>" : null)}");
            //
            var e = new Dictionary<string, string> {
                { "ExecutionTime", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") },
                { "Method", $"{Handler} {(IsException ? "出错" : "")}" },
                { "CommandType", $"{(CMD.CommandType == CommandType.StoredProcedure ? "存储过程" : "SQL语句")}" },
                { "Command", $"{SQL}" },
                { "RunTime", $"{Timer.ElapsedMilliseconds} 毫秒" },
                { "Parameters", $"{(CMD.Parameters.Count > 0 ? cmdParms : null)}"},
                { "Exception", Message}
            };
            Common.WriteLog(Common.Serialize(e), Key);
        }
    }
    /// <summary>
    /// 
    /// </summary>
    internal static (string,string) Parse(DbCommand CMD) {
        if (CMD == null) {
            return (null, null);
        }
        var SQL = CMD.CommandText;
        var StoredProcedure = false;
        var sb = new StringBuilder();
        var sp = new StringBuilder();
        if (CMD.CommandType == CommandType.StoredProcedure) {
            StoredProcedure = true;
        }
        if (CMD.Parameters.Count > 0) {
            //
            // sb.Append($"命令参数：<br/>");
            //
            foreach (DbParameter P in CMD.Parameters) {
                var ParameterKey = P.ParameterName;
                string Value;
                if (P.Value == DBNull.Value) {
                    Value = "NULL";
                } else {
                    if (Common.IsNumber(P.Value)) {
                        Value = P.Value.ToString();
                    } else {
                        Value = P.DbType switch {
                            DbType.Boolean => P.Value.ToString(),
                            DbType.DateTime or 
                            DbType.DateTime2 or 
                            DbType.Date or 
                            DbType.DateTimeOffset or 
                            DbType.Time => 
                            $"\"{P.Value.ToString().Replace('/','-')}\"",
                            _ => 
                            $"\"{Convert.ToString(P.Value)}\"",
                        };
                    }
                }
                //
                sb.Append($"Parameter[\"{ParameterKey}\"] = {Value} DbType = {P.DbType.ToString()}；");
                //
                if (StoredProcedure) {
                    sp.Append($"{P.ParameterName}={Value},");
                } else {
                    SQL = SQL.Replace(P.ParameterName, Value);
                }
            }
        }
        if (StoredProcedure) {
            SQL = $"EXEC {SQL} {sp}";
        }
        return (SQL, sb.ToString());
    }

    #endregion

    #region "处理SQL参数"

    /// <summary>
    /// 添加SQL参数，返回参数对象
    /// </summary>
    /// <returns></returns>
    public static DbParameter AddParameter(this DataBase db, string Name, object Value = null, DbType? dbType = null, ParameterDirection Direction = ParameterDirection.InputOutput) {
        var e = db.Provider.CreateParameter();
        if (Name.StartsWith(db.ParameterChar)) {
            e.ParameterName = Name;
        } else {
            e.ParameterName = $"{db.ParameterChar}{Name}";
        }
        if (dbType.HasValue) {
            e.DbType = dbType.Value;
        }
        e.Value = Value ?? DBNull.Value;
        e.Direction = Direction;
        return e;
    }
    /// <summary>
    /// 添加SQL参数
    /// </summary>
    internal static void AddParameter(DataBase db, DbCommand CMD, IList<DbParameter> cmdParams) {
        if (cmdParams != null && cmdParams.Count > 0) {
            for (var i = 0; i < cmdParams.Count; i++) {
                var P = cmdParams.ElementAt(i);
                if (CMD.Parameters.Contains(P.ParameterName)) {
                    cmdParams.RemoveAt(i); i--;
                } else {
                    var e = db.Provider.CreateParameter();
                    e.ParameterName = P.ParameterName;
                    e.DbType = P.DbType;
                    e.Value = P.Value;
                    e.Direction = P.Direction;
                    CMD.Parameters.Add(e);
                }
            }
        }
    }
    /// <summary>
    /// 处理返回数据
    /// </summary>
    internal static void ProcessReturnValue(DbCommand CMD, IList<DbParameter> cmdParams) {
        if (cmdParams != null && CMD.Parameters.Count > 0) {
            var List = cmdParams.Where((e) => e.Direction == ParameterDirection.ReturnValue);
            foreach (DbParameter P in CMD.Parameters) {
                if (P.Direction == ParameterDirection.ReturnValue) {
                    var e = List.Where((e) => e.ParameterName == P.ParameterName).FirstOrDefault();
                    if (e != null) {
                        e.Value = P.Value;
                        e.DbType = P.DbType;
                    }
                }
            }
        }
    }

    #endregion

    #region "DataReader 转为 IList<T>"

    /// <summary>
    /// DataReader 转为 IList&lt;T&gt; 泛型 (不用执行与Rs.Read()相关的判断语句 )
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="DataReader"></param>
    /// <param name="Delegate">数据行委托处理方法</param>
    /// <returns></returns>
    public static IList<T> ToCollection<T>(this IDataReader DataReader, Action<T, IDataReader> Delegate = null) {
        IList<T> List = [];
        if (DataReader == null) {
            return List;
        }
        var et = Entity.Create(typeof(T));
        var IsDelegate = (Delegate != null);
        while (DataReader.Read()) {
            var e = Activator.CreateInstance<T>();
            if (IsDelegate) {
                Delegate.Invoke(e, DataReader);
            }
            List.Add(DataReader.ToEntity<T>(e, et));
        }
        return List;
    }
    /// <summary>
    /// 
    /// </summary>
    private static T ToEntity<T>(this IDataReader Rs, T e, Entity et) {
        object Value;
        string Key;
        for (int i = 0; i < Rs.FieldCount; i++) {
            Key = Rs.GetName(i);
            Value = Rs.GetValue(i);
            Column P;
            if (et.Fields.TryGetValue(Key, out Column _Value)) {
                P = _Value;
            } else {
                if (et.Propertys.TryGetValue(Key, out Column __Value)) {
                    P = __Value;
                } else {
                    P = null;
                }
            }
            try {
                if (P == null || !P.That.CanWrite) {
                    continue;
                }
                switch (P.PropertyType) {
                    case PropertyType.PrimitiveType:
                        break;
                    case PropertyType.EnumType:
                        if (Value != null) {
                            try {
                                Value = Enum.Parse(P.Type, Value.ToString(), true);
                            } catch { }
                        }
                        break;
                    default:
                        Value = Common.Deserialize(Value, P.Type);
                        break;
                }
                P.That.SetValue(e, Value);
            } catch {

            }
        }
        return e;
    }

    #endregion

    #region "DataReader 转为 IList<Hashtable>、JSon 格式字符串"

    /// <summary>
    /// DataReader 转为 IList&lt;Hashtable&gt; 类型（不用执行与Rs.Read()相关的判断语句）
    /// <para>1.自定义输出名称："UID,Name.As.FullName,Password,Sex,Age"，格式如：字段原名.As.别名;</para>
    /// <para>2.自定义输出名称："UID,Name:FullName,Password,Sex,Age"，格式如：字段原名:别名;</para>
    /// <para>3.要忽略的字段列："@,Password,Age"</para>
    /// </summary>
    /// <param name="DataReader"></param>
    /// <param name="Columns">自定义输出字段列表</param>
    /// <param name="Delegate">数据行委托处理方法</param>
    /// <returns></returns>
    public static IList<Hashtable> ToCollection(this IDataReader DataReader, string Columns = null, Action<Hashtable, IDataReader> Delegate = null) {
        IList<Hashtable> List = [];
        var IsDelegate = (Delegate != null);
        while (DataReader.Read()) {
            Hashtable e = ToEntity(DataReader, Columns);
            if (IsDelegate) {
                Delegate.Invoke(e, DataReader);
            }
            List.Add(e);
        }
        return List;
    }
    /// <summary>
    /// 
    /// </summary>
    private static Hashtable ToEntity(IDataReader Rs, string Columns = null) {
        Hashtable et = [];
        Parts e = null;
        if (!string.IsNullOrEmpty(Columns)) {
            e = Common.Parse(Columns);
        }
        for (int i = 0; i < Rs.FieldCount; i++) {
            var Key = Rs.GetName(i);
            if (e != null) {
                if (e.Ignore) {
                    if (e.Keys.Contains(Key)) {
                        continue;
                    }
                } else {
                    if (e.Keys.Contains(Key)) {
                        if (e.Alias.TryGetValue(Key, out string Value)) {
                            Key = Value;
                        }
                    } else {
                        continue;
                    }
                }
            }
            et.Add(Key, Rs.GetValue(i));
        }
        return et;
    }
    /// <summary>
    /// DataReader 转为 JSon 格式字符串, 格式如：[{..},{..},..] (不用执行与Rs.Read()相关的判断语句 )
    /// <para>1.自定义输出名称："UID,Name.As.FullName,Password,Sex,Age"，格式如：字段原名.As.别名;</para>
    /// <para>2.自定义输出名称："UID,Name:FullName,Password,Sex,Age"，格式如：字段原名:别名;</para>
    /// <para>3.要忽略的字段列："@,Password,Age"</para>        /// </summary>
    public static string Serialize(this IDataReader DataReader, string Columns = null) {
        var sb = new StringBuilder();
        while (DataReader.Read()) {
            sb.Append(Parse(DataReader, Columns)).Append(',');
        }
        return string.Concat("[", sb.ToString().TrimEnd(','), "]");
    }
    /// <summary>
    /// 
    /// </summary>
    private static string Parse(IDataReader Rs, string Columns = null) {
        var sb = new StringBuilder();
        Parts e = null;
        if (!string.IsNullOrEmpty(Columns)) {
            e = Common.Parse(Columns);
        }
        for (int i = 0; i < Rs.FieldCount; i++) {
            var Key = Rs.GetName(i);
            if (e != null) {
                if (e.Ignore) {
                    if (e.Keys.Contains(Key)) {
                        continue;
                    }
                } else {
                    if (e.Keys.Contains(Key)) {
                        if (e.Alias.TryGetValue(Key, out string Value)) {
                            Key = Value;
                        }
                    } else {
                        continue;
                    }
                }
            }
            sb.Append(string.Concat("\"", Key, "\":", Rs.GetValue(i).ToValue(), ","));
        }
        return string.Concat("{", sb.ToString().TrimEnd(','), "}");
    }

    #endregion

    #region "DataTabale 转为 IList<T>"

    /// <summary>
    /// DataTable 转为 IList&lt;T&gt; 泛型
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="dt"></param>
    /// <param name="Delegate">数据行委托处理方法</param>
    /// <returns></returns>
    public static IList<T> ToCollection<T>(this DataTable dt, Action<T, DataRow> Delegate = null) {
        IList<T> List = [];
        if (dt == null) {
            return List;
        }
        var et = Entity.Create(typeof(T));
        var IsDelegate = (Delegate != null);
        foreach (DataRow Rs in dt.Rows) {
            var e = Activator.CreateInstance<T>();
            if (IsDelegate) {
                Delegate.Invoke(e, Rs);
            }
            List.Add(Rs.ToEntity<T>(e, et));
        }
        return List;
    }
    /// <summary>
    /// 
    /// </summary>
    private static T ToEntity<T>(this DataRow Rs, T e, Entity et) {
        object Value;
        string Key;
        foreach (DataColumn Column in Rs.Table.Columns) {
            Key = Column.ColumnName;
            Value = Rs[Key];
            if (Value == DBNull.Value) {
                Value = null;
            }
            Column P;
            if (et.Fields.TryGetValue(Key, out Column _Value)) {
                P = _Value;
            } else {
                if (et.Propertys.TryGetValue(Key, out Column __Value)) {
                    P = __Value;
                } else {
                    P = null;
                }
            }
            try {
                if (P == null || !P.That.CanWrite) {
                    continue;
                }
                switch (P.PropertyType) {
                    case PropertyType.PrimitiveType:
                        break;
                    case PropertyType.EnumType:
                        if (Value != null) {
                            try {
                                Value = Enum.Parse(P.Type, Value.ToString(), true);
                            } catch { }
                        }
                        break;
                    default:
                        Value = Common.Deserialize(Value, P.Type);
                        break;
                }
                P.That.SetValue(e, Value);
            } catch {

            }
        }
        return e;
    }

    #endregion

    #region "DataTable 转为 IList<Hashtable>、JSon 格式字符串"

    /// <summary>
    /// DataTable 转为 IList&lt;Hashtable&gt; 哈希表集合
    /// <para>1.自定义输出名称："UID,Name.As.FullName,Password,Sex,Age"，格式如：字段原名.As.别名;</para>
    /// <para>2.自定义输出名称："UID,Name:FullName,Password,Sex,Age"，格式如：字段原名:别名;</para>
    /// <para>3.要忽略的字段列："@,Password,Age"</para>
    /// </summary>
    /// <param name="Table"></param>
    /// <param name="Columns"></param>
    /// <param name="Delegate">数据行委托处理方法</param>
    /// <returns></returns>
    public static IList<Hashtable> ToCollection(this DataTable Table, string Columns = null, Action<Hashtable, DataRow> Delegate = null) {
        IList<Hashtable> List = [];
        bool IsDelegate = (Delegate != null);
        foreach (DataRow Rs in Table.Rows) {
            Hashtable e = ToEntity(Rs, Columns);
            if (IsDelegate) {
                Delegate.Invoke(e, Rs);
            }
            List.Add(e);
        }
        return List;
    }
    /// <summary>
    /// 
    /// </summary>
    private static Hashtable ToEntity(DataRow Rs, string Columns = null) {
        var Hash = new Hashtable();
        Parts e = null;
        if (!string.IsNullOrEmpty(Columns)) {
            e = Common.Parse(Columns);
        }
        foreach (DataColumn Ros in Rs.Table.Columns) {
            var Key = Ros.ColumnName;
            if (e != null) {
                if (e.Ignore) {
                    if (e.Keys.Contains(Key)) {
                        continue;
                    }
                } else {
                    if (e.Keys.Contains(Key)) {
                        if (e.Alias.TryGetValue(Key, out string Value)) {
                            Key = Value;
                        }
                    } else {
                        continue;
                    }
                }
            }
            Hash.Add(Key, (Rs[Key] == DBNull.Value ? null : Rs[Key]));
        }
        return Hash;
    }
    /// <summary>
    /// DataTable 转为 JSon 格式字符串, 格式如：[{..},{..},..] 
    /// <para>1.自定义输出名称："UID,Name.As.FullName,Password,Sex,Age"，格式如：字段原名.As.别名;</para>
    /// <para>2.自定义输出名称："UID,Name:FullName,Password,Sex,Age"，格式如：字段原名:别名;</para>
    /// <para>3.要忽略的字段列："@,Password,Age"</para>
    /// </summary>
    /// <param name="Table"></param>
    /// <param name="Columns"></param>
    /// <returns></returns>
    public static string Serialize(DataTable Table, string Columns = null) {
        var sb = new StringBuilder();
        foreach (DataRow Rs in Table.Rows) {
            sb.Append(Parse(Rs, Columns)).Append(',');
        }
        return string.Concat("[", sb.ToString().TrimEnd(','), "]");
    }
    /// <summary>
    /// 
    /// </summary>
    private static string Parse(DataRow Rs, string Columns = null) {
        var sb = new StringBuilder();
        Parts e = null;
        if (!string.IsNullOrEmpty(Columns)) {
            e = Common.Parse(Columns);
        }
        foreach (DataColumn Ros in Rs.Table.Columns) {
            var Key = Ros.ColumnName;
            if (e != null) {
                if (e.Ignore) {
                    if (e.Keys.Contains(Key)) {
                        continue;
                    }
                } else {
                    if (e.Keys.Contains(Key)) {
                        if (e.Alias.TryGetValue(Key, out string Value)) {
                            Key = Value;
                        }
                    } else {
                        continue;
                    }
                }
            }
            sb.Append('"').Append(Key).Append("\":").Append(Rs[Key].ToValue()).Append(',');
        }
        return string.Concat("{", sb.ToString().TrimEnd(','), "}");
    }

    #endregion

}

